/**********************************************************************

  Audacity: A Digital Audio Editor

  EffectManager.h

  Audacity(R) is copyright (c) 1999-2008 Audacity Team.
  License: GPL v2 or later.  See License.txt.

**********************************************************************/

#ifndef __AUDACITY_EFFECTMANAGER__
#define __AUDACITY_EFFECTMANAGER__

#include "EffectInterface.h"
#include "Identifier.h"

#include <functional>
#include <memory>
#include <unordered_map>
#include <variant>
#include <vector>

class AudacityProject;
class CommandContext;
class ComponentInterfaceSymbol;
class wxString;
typedef wxString PluginID;
class Effect;
class EffectPlugin;
struct EffectSettings;
class EffectInstance;

struct EffectAndDefaultSettings {
    EffectPlugin* effect{};
    EffectSettings settings{};
};

using EffectMap = std::unordered_map<wxString, EffectAndDefaultSettings>;
using EffectOwnerMap = std::unordered_map< wxString, std::shared_ptr<EffectPlugin> >;

EFFECTS_API
RegistryPaths GetUserPresets(EffectPlugin& host);

EFFECTS_API
bool HasCurrentSettings(EffectPlugin& host);

EFFECTS_API
bool HasFactoryDefaults(EffectPlugin& host);

class EFFECTS_API EffectManager
{
public:

    enum : unsigned {
        // No flags specified
        kNone = 0x00,
        // Flag used to disable prompting for configuration parameteres.
        kConfigured = 0x01,
        // Flag used to disable saving the state after processing.
        kSkipState = 0x02,
        // Flag used to disable "Repeat Last Effect"
        kDontRepeatLast = 0x04,
        // Flag used to disable "Select All during Repeat Generator Effect"
        kRepeatGen = 0x08,
        // Flag used for repeating Nyquist Prompt
        kRepeatNyquistPrompt = 0x10,
    };

    /*! Find the singleton EffectInstanceFactory for ID. */
    static const EffectInstanceFactory*
    GetInstanceFactory(const PluginID& ID);

    /** Get the singleton instance of the EffectManager. Probably not safe
        for multi-thread use. */
    static EffectManager& Get();

    //
    // public methods
    //
    // Used by the outside program to register the list of effects and retrieve
    // them by index number, usually when the user selects one from a menu.
    //
public:
    using EffectPresetDialog = std::function<std::optional<wxString>(
                                                 EffectPlugin&, const wxString& preset)>;

    //! Here solely for the purpose of Nyquist Workbench until a better solution is devised.
    /** Register an effect so it can be executed.
      uEffect is expected to be a self-hosting Nyquist effect */
    const PluginID& RegisterEffect(std::unique_ptr<EffectPlugin> uEffect);
    //! Used only by Nyquist Workbench module
    void UnregisterEffect(const PluginID& ID);

    TranslatableString GetEffectFamilyName(const PluginID& ID);
    TranslatableString GetVendorName(const PluginID& ID);

    bool IsHidden(const PluginID& ID);

    bool HasPresets(const PluginID& ID);
    wxString
    GetPreset(const PluginID& ID, const wxString& params, EffectPresetDialog);
    wxString GetDefaultPreset(const PluginID& ID);

    /** Allow effects to disable saving the state at run time */
    void SetSkipStateFlag(bool flag);
    bool GetSkipStateFlag();

    /*! Return an effect by its ID. */
    EffectPlugin* GetEffect(const PluginID& ID);

    /*! Get default settings by effect ID.  May return nullptr */
    EffectSettings* GetDefaultSettings(const PluginID& ID);

    /*! Get effect and default settings by effect ID. */
    /*!
     @post `result: !result.first || result.second`
     (if first member is not null, then the second is not null)
     */
    std::pair<EffectPlugin*, EffectSettings*>
    GetEffectAndDefaultSettings(const PluginID& ID);

private:
    EffectAndDefaultSettings& DoGetEffect(const PluginID& ID);

    EffectMap mEffects;
    EffectOwnerMap mHostEffects;

    int mNumEffects;

    // Set true if we want to skip pushing state
    // after processing at effect run time.
    bool mSkipStateFlag;
};

#endif
